package com.ddframework.orm.dao;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import com.ddframework.bean.Book;
import com.ddframework.bean.Style;
import com.ddframework.orm.datasource.DBControl;
import com.ddframework.orm.tools.Constant;
import com.ddframework.tableinfo.Id;
import com.ddframework.tableinfo.ManytoOne;
import com.ddframework.tableinfo.OnetoMany;
import com.ddframework.tableinfo.Property;
import com.ddframework.tableinfo.TableInfo;

public class BaseDAOImpl implements BaseDAO {
	private DBControl db;

	@Override
	public void save(Object o) {
		db = new DBControl();
		Class c = o.getClass();
		String classname = c.getName();
		TableInfo table = Constant.TABLEMAP.get(classname);
		Id id = table.getId();
		List<Property> plist = table.getPlist();
		List<ManytoOne> manylist = table.getManylist();
		String idname = id.getIdname();
		String idcolumn = id.getIdcolumn();
		Object idvalue = getValueByObject(idname, o);
		System.out.println(idvalue);
		StringBuffer sb = new StringBuffer("insert into ").append(
				table.getTablename()).append(" (");
		sb.append(idcolumn).append(",");
		List<Object> valuelist = new ArrayList<Object>();
		if (plist != null) {
			for (Property p : plist) {
				String pname = p.getPropertyname();
				String pcolumn = p.getPropertycolumn();
				sb.append(pcolumn).append(",");
				valuelist.add(getValueByObject(pname, o));

			}

		}
		if (manylist != null) {
			// have foreign key, need to insert
			for (ManytoOne many : manylist) {
				String manyname = many.getManyname();
				String manycolumn = many.getManycolumn();
				Object manyobject = getValueByObject(manyname, o);
				Object manyvalue = getValueByObject(manycolumn, manyobject);
				sb.append(manycolumn).append(",");
				valuelist.add(manyvalue);

			}

		}
		// Until now, all fields have been prepared.
		// remove the last comma of this string
		String sqlStr = sb.substring(0, sb.toString().length() - 1);
		sqlStr += ") values(" + idvalue + ",";
		for (Object value : valuelist) {
			sqlStr += "'" + value + "',";
		}
		sqlStr = sqlStr.substring(0, sqlStr.length() - 1) + ")";
		System.out.println(sqlStr);
		db.setData(sqlStr);
		db.close();
	}

	private Object getValueByObject(String name, Object o) {
		Field f = null;
		Object value = null;
		try {
			f = o.getClass().getDeclaredField(name);
			f.setAccessible(true);
			value = f.get(o);
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return value;

	}

	@Override
	public void update(Object o) {
		db = new DBControl();
		Class c = o.getClass();
		String classname = c.getName();
		TableInfo table = Constant.TABLEMAP.get(classname);
		Id id = table.getId();
		String idname = id.getIdname();
		String idcolumn = id.getIdcolumn();
		Object idvalue = getValueByObject(idname, o);
		List<String> columnlist = new ArrayList<String>();
		List<Object> valuelist = new ArrayList<Object>();
		List<Property> plist = table.getPlist();
		for (Property p : plist) {
			String pname = p.getPropertyname();
			Object pvalue = getValueByObject(pname, o);
			if (pvalue != null) {
				valuelist.add(pvalue);
				columnlist.add(p.getPropertycolumn());

			}
		}
		List<ManytoOne> manylist = table.getManylist();
		if (manylist != null) {
			for (ManytoOne many : manylist) {
				String manyname = many.getManyname();
				Object manyvalue = getValueByObject(manyname, o);
				if (manyvalue != null) {
					String manycolumn = many.getManycolumn();
					Object mvalue = getValueByObject(manycolumn, manyvalue);
					valuelist.add(mvalue);
					columnlist.add(manycolumn);
				}
			}
		}
		if(valuelist.size()==0){			
			System.out.println("No update any field!");
			db.close();
			return;
		}
		StringBuffer sb = new StringBuffer("update ");
		sb.append(table.getTablename()).append(" set ");
		for (int i = 0; i < valuelist.size(); i++) {
			String column = columnlist.get(i);
			Object value = valuelist.get(i);
			sb.append(column).append("='").append(value).append("',");
		}
		// update book set field1=value1, field2=value2
		String sql = sb.toString();
		sql = sql.substring(0, sql.length() - 1);
		sql += " where " + idname + "=" + idvalue;
		System.out.println(sql);
		db.setData(sql);
		db.close();
		
	}

	@Override
	public void del(Object o) {
		// delete from tablename where condition(primary key=XXX)
		db = new DBControl();
		Class c = o.getClass();
		String classname = c.getName();
		TableInfo table = Constant.TABLEMAP.get(classname);
		List<OnetoMany> onelist = table.getOnelist();
		// onelist represent one-to-many relationship, if the list is not empty,
		// it means that this table
		// has cascade relationship, it cannot be deleted
		if (onelist != null) {
			System.out.println("Have cascade relationship, cannot be deleted");
			db.close();
			return;
		}
		Id id = table.getId();
		String idcolumn = id.getIdcolumn();
		String idname = id.getIdname();
		Object idvalue = getValueByObject(idname, o);
		if (null == idvalue) {
			System.out.println("The primary key is not set!");
		}
		String sql = "delete from " + table.getTablename() + " where "
				+ idcolumn + "=" + idvalue;
		System.out.println(sql);
		db.setData(sql);

	}

	@Override
	public Object query(String dql) {

		return null;
	}

	@Override
	public List queryList(String dql) {
		// TODO Auto-generated method stub
		return null;
	}

	public static void main(String[] args) {
		BaseDAO dao = new BaseDAOImpl();
		Style style = new Style();
		style.setStyleId(2);
		style.setStyle("Computer1");
		Book book = new Book();
		book.setBookId(3);
		//book.setBookname("Steve Jobs");
		//book.setAuthor("Steve");
		book.setStyle(style);
		book.setPublisher("OxBridge");
		dao.update(book);

	}
}
